package def

import (
	"fmt"
	"reflect"
	"strings"
	"strconv"
)


type GeneratedStaticDataSeed struct {
	DispatchTables  [] DispatchTableSeed
	TransformPaths  [] InterfaceTransformPath
}
type DispatchTableSeed struct {
	Id  DispatchTableIdentifier
}
func (s DispatchTableSeed) Evaluate(m DispatchTableMapping) *DispatchTable {
	var d, exists = m[s.Id]
	if !(exists) {
		panic(fmt.Sprintf("unable to retrieve v-table %s", s.Id))
	}
	return d
}

type StaticValueSeed interface {
	Evaluate(ctx StaticValueSeedEvaluator) Value
	Key() (string, bool)
	fmt.Stringer
}
type StaticValueSeedEvaluator struct {
	MustGetFuncValue  func(Symbol)(FuncValue)
}

type StaticValueSeedVariant struct {
	Value  Value
}
func (s StaticValueSeedVariant) String() string {
	var v = s.Value
	var t = reflect.TypeOf(v)
	return fmt.Sprintf("%s %v", t, v)
}
func (s StaticValueSeedVariant) Key() (string, bool) {
	return s.String(), true
}
func (s StaticValueSeedVariant) Evaluate(_ StaticValueSeedEvaluator) Value {
	return s.Value
}

type StaticValueSeedFunctionReference struct {
	Symbol  Symbol
}
func (s StaticValueSeedFunctionReference) String() string {
	return fmt.Sprintf("ref func %s", s.Symbol)
}
func (s StaticValueSeedFunctionReference) Key() (string, bool) {
	return s.String(), true
}
func (s StaticValueSeedFunctionReference) Evaluate(ctx StaticValueSeedEvaluator) Value {
	return ctx.MustGetFuncValue(s.Symbol)
}

type StaticValueSeedStringFormatter struct {
	Template    string
	Parameters  [] uint
}
func (s StaticValueSeedStringFormatter) String() string {
	return fmt.Sprintf("formatter %s", strconv.Quote(s.Template))
}
func (s StaticValueSeedStringFormatter) Key() (string, bool) {
	return "", false
}
func (s StaticValueSeedStringFormatter) Evaluate(_ StaticValueSeedEvaluator) Value {
	if len(s.Parameters) == 0 {
		panic("invalid string formatter seed")
	}
	var arity = len(s.Parameters)
	var template = s.Template
	var parameters = s.Parameters
	return ValFuncNative(func(arg Value, _ InteropContext) Value {
		var args = (func() ([] Value) {
			if arity == 1 {
				return [] Value { arg }
			} else {
				return arg.(TupleValue).Elements
			}
		})()
		var buf strings.Builder
		var x = uint(0)
		for i, y := range parameters {
			buf.WriteString(template[x:y])
			buf.WriteString(args[i].(string))
			x = (y + 1)
		}
		buf.WriteString(template[x:])
		return buf.String()
	})
}

type StaticValueSeedStringLiteral struct {
	Value  string
}
func (s StaticValueSeedStringLiteral) String() string {
	return fmt.Sprintf("string %s", strconv.Quote(s.Value))
}
func (s StaticValueSeedStringLiteral) Key() (string, bool) {
	const StringLiteralConstPoolThreshold = 32
	var v = s.Value
	if len(v) <= StringLiteralConstPoolThreshold {
		return v, true
	} else {
		return "", false
	}
}
func (s StaticValueSeedStringLiteral) Evaluate(_ StaticValueSeedEvaluator) Value {
	return s.Value
}


